package com.ctshk.rpc.cms.config;

import com.ctshk.common.constant.RedisConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;

import java.nio.charset.Charset;
import java.time.Duration;

/**
 * @description redis配置
 * @author 谢诗宏
 * @date 2020/12/16
 */
@Configuration
@EnableCaching
public class RedisConfig {

	/**
	 * 实例化 RedisTemplate 对象
	 *
	 * @return
	 */
	@Bean
	public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
		// 设置数据存入 redis 的序列化方式
		redisTemplate.setKeySerializer(keySerializer());
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
		redisTemplate.setValueSerializer(new RedisValueSerializer());
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		// 不开启事务，用到事务都在lua脚本自己写
        redisTemplate.setEnableTransactionSupport(false);
		return redisTemplate;
	}

	@Primary
	@Bean
	public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
		// 缓存配置对象
		RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
		//设置缓存的默认超时时间：30分钟
		redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30))
				// 如果是空值，不缓存
				.disableCachingNullValues()
				// 设置key序列化器
				.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
				// 设置value序列化器
				.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));
		return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();
	}
	private RedisSerializer<String> keySerializer() {
		//自定义key序列号，加上统一前缀，统一管理key
		return new RedisSerializer<String>(){
			private final Charset charset = Charset.forName("UTF-8");
			@Override
			public byte[] serialize(String key) throws SerializationException {
				if(StringUtils.isBlank(key)) throw new SerializationException("empty key");
				String keyPrefix = RedisConstants.KEY_PREFIX;
		        String key2 = keyPrefix + key;
		        return key2.getBytes(charset);
			}
			@Override
			public String deserialize(byte[] bytes) throws SerializationException {
				String keyPrefix = RedisConstants.KEY_PREFIX;
		        String key = new String(bytes, charset);
		        int idx = key.indexOf(keyPrefix);
		        if (idx == -1) {
		        	throw new SerializationException("found key without prefix");
		        } else {
		        	key = key.substring(idx + keyPrefix.length());
		        }
		        return key;
			}
		};
	}
	private RedisSerializer<Object> valueSerializer() {
		return new JdkSerializationRedisSerializer();
	}

}
